package dto

import (
	"encoding/json"
	"strings"
	"time"

	"code.bydev.io/cht/customer/kyc-stub.git/pkg/bybit/kyc/common/enums"
	"git.bybit.com/svc/stub/pkg/pb/api/consts/euser"
	"git.bybit.com/svc/stub/pkg/pb/enums/epageaction"
	"git.bybit.com/svc/stub/pkg/pb/enums/kyc"
)

// KYCRecord requests
type KYCRecord struct {
	MemberID       int64
	ExternalUserID string // hashid
	ApplicantID    string
	Country        string
	Provider       KYCProvider
	LevelName      string
	Level          KYCLevel
	InspectionID   string
	Applicant      *Applicant
	Documents      map[string]*Document
	State          ReviewState
	Result         ReviewResult
	Retry          int
	RejectLabels   []string
	Type           KYCType
	Residence      string
	Nationality    string
}
type KYCRequiredInfo struct {
	MemberID int64
	Reason   string
	Deadline time.Time
}

type SetKYCRecordResidenceAndNationality struct {
	MemberID    int64
	Residence   string
	Nationality string
}
type Document struct {
	ID     string       `json:"id"`
	Bucket string       `json:"bucket"`
	Key    string       `json:"key"`
	Mime   string       `json:"mime"`
	Type   DocumentType `json:"type"`
	Data   []byte       `json:"-"`
	Tag    string       `json:"tag"`
}

func (k *KYCRecord) GetMemberID() int64 {
	return k.MemberID
}

func (k *KYCRecord) GetProvider() int8 {
	return int8(k.Provider)
}

func (k *KYCRecord) GetCountry() string {
	return k.Country
}

func (k *KYCRecord) GetApplicant() string {
	if k.Applicant == nil {
		return ""
	}
	b, _ := json.Marshal(k.Applicant)
	return string(b)
}

func (k *KYCRecord) UnmarshalApplicant(data string) *Applicant {
	a := new(Applicant)
	if err := json.Unmarshal([]byte(data), a); err != nil {
		return nil
	}

	k.Applicant = a
	return k.Applicant
}

func (k *KYCRecord) CanRetry() bool {
	return k.Retry > CantRetry
}

func (k *KYCRecord) GetLevel() int8 {
	return int8(k.Level)
}

func (k *KYCRecord) GetLevelName() string {
	return k.LevelName
}

func (k *KYCRecord) GetApplicantID() string {
	return k.ApplicantID
}

func (k *KYCRecord) GetInspectionID() string {
	return k.InspectionID
}

func (k *KYCRecord) GetExternalUserID() string {
	return k.ExternalUserID
}

func (k *KYCRecord) GetType() int8 {
	return int8(k.Type)
}

func (k *KYCRecord) GetState() int8 {
	return int8(k.State)
}

func (k *KYCRecord) GetResult() int8 {
	return int8(k.Result)
}

func (k *KYCRecord) GetRejectLabels() string {
	if k.Result == ReviewResultReject {
		return strings.Join(k.RejectLabels, ",")
	}

	return ""
}

func (k *KYCRecord) GetDocuments() string {
	b, _ := json.Marshal(k.Documents)
	return string(b)
}

func (k *KYCRecord) ParseRejectLabels(labels string) []string {
	ls := strings.Split(labels, ",")
	k.RejectLabels = ls
	return ls
}

func (k *KYCRecord) UnmarshalDocuments(data string) map[string]*Document {
	docs := make(map[string]*Document)
	if err := json.Unmarshal([]byte(data), &docs); err != nil {
		return nil
	}

	k.Documents = docs
	return docs
}

func (k *KYCRecord) MergeDocuments(data string) string {
	if data == "" {
		return k.GetDocuments()
	}

	if k.Documents == nil {
		return data
	}

	docs := make(map[string]*Document)
	if err := json.Unmarshal([]byte(data), &docs); err != nil {
		return ""
	}

	for key, doc := range docs {
		if _, ok := k.Documents[key]; ok {
			continue
		}
		k.Documents[key] = doc
	}

	return k.GetDocuments()
}
func (k *KYCRecord) GetResidence() string {
	return k.Residence
}
func (k *KYCRecord) GetNationality() string {
	return k.Nationality
}

type ServiceData struct {
	MemberID  int64
	Level     int8
	Country   string
	Type      int8
	Result    int8
	Applicant string
	Documents string
}
type KycVendorConfigInfo struct {
	Switch        bool               `json:"switch"`          // 是否使用配置
	CountryCode   string             `json:"country_code"`    // 国家码(2位字符串, 如CN)
	CountryCodeEn string             `json:"country_code_en"` // 国家码英文名
	CountryCodeCn string             `json:"country_code_cn"` // 国家码中文
	Mod           int64              `json:"mod"`             // 流量切片取模值
	Detail        []*KycVendorDetail `json:"detail"`          // 国家配置详情
}

type KycVendorDetail struct {
	Vendor int64 `json:"vendor"` // 服务商标识 1: sumsub 2: jumio
	Min    int64 `json:"min"`    // 取模后的值的下限
	Max    int64 `json:"max"`    // 取模后的值的上限
}

type SearchKYCRecordCondition struct {
	MemberID     int64                  `json:"member_id,omitempty"`
	ApplicantID  string                 `json:"applicant_id,omitempty"`
	State        kyc.MemberKYCState     `json:"state,omitempty"`
	Status       euser.BanCategory      `json:"status,omitempty"`
	Type         kyc.MemberKYCType      `json:"type,omitempty"`
	Result       kyc.MemberKYCResult    `json:"result,omitempty"`
	CreatedStart string                 `json:"created_start,omitempty"`
	CreatedEnd   string                 `json:"created_end,omitempty"`
	Action       epageaction.PageAction `json:"actionsvc,omitempty"`
	FollowAction kyc.KYCFollowAction    `json:"follow_action,omitempty"`
	Provider     kyc.KYCProvider        `json:"provider,omitempty"`
	PageSize     int32                  `json:"page_size,omitempty"` // 翻页
	Cursor       string                 `json:"cursor,omitempty"`    // 游标
}

type DocDetail struct {
	MemberID     int64
	BrokerID     euser.BrokerID
	Provider     KYCProvider
	ProviderUUID string
	IssueCountry string
	DocType      DocType
	SubType      SubDocType
	DocNumber    string
	Identifier   string
	Valid        bool
	ExtraData    DocExtraData
}

type DocExtraData struct {
}

type KYCAdminDetail struct {
	ProviderDecision     int8                  // provider_decision 服务商认证结果(0:unknown, 1:success, 2:reject)
	ProviderRejectReason string                // provider_reject_reason 服务商拒绝原因
	DocType              int8                  // doc_type 证件大类
	DocSubtype           int8                  // doc_subtype 证件子类
	DocNumber            string                // doc_number 证件号(密文)
	Country              string                // country 证件签发国(KYC国籍)
	Nationality          string                // nationality 原籍
	AddressCountry       string                // address_country 居住国
	FirstName            string                // first_name 名字(密文)
	LastName             string                // last_name 姓氏(密文)
	Dob                  string                // dob 出生日期(密文)
	ProviderCreateAt     int64                 // provider_create_at 供应商回调时间(时间戳 ms)
	DocDetail            KYCAdminDocDetail     // doc_detail 证件详情，JSON(密文)
	IssuingDate          string                // issuing_date 签发日期
	ExpireDate           string                // expire_date 有效期
	FaceDetail           KYCAdminFaceDetail    // face_detail 人脸详情，JSON(密文)
	AddressDetail        KYCAdminAddressDetail // address_detail 地址详情，JSON(密文)
	ClientDetail         KYCAdminClientDetail  // client_detail 客户端详情，JSON
	ReviewAtE3           int64                 // Reviewdate 回调时间
}

type KYCAdminClientDetail struct {
	ClientIP string `json:"client_ip"` // 通道返回的客户端IP
	From     string `json:"from"`      // 中台自己记录的设备细分（Android、iOS、Web）
	Source   string `json:"source"`    // 通道返回的客户端的源
}

type KYCAdminAddressDetail struct {
	Country     string `json:"country"`
	State       string `json:"state"`
	City        string `json:"city"`
	FullAddress string `json:"full_address"`
	PostalCode  string `json:"postal_code"`
}

type KYCAdminDocDetail struct {
	DocFront       string `json:"doc_front"`
	DocBack        string `json:"doc_back"`
	PersonalNumber string `json:"personal_number"`
}

type KYCAdminFaceDetail struct {
	FaceImage         string `json:"face_image"`
	LivenessImage     string `json:"liveness_image"`
	SimilarityChecked string `json:"similarity_checked"`
	ValidityChecked   string `json:"validity_checked"`
}

type KYCAdminImage struct {
	Front int `json:"front"`
	Back  int `json:"back"`
	Face  int `json:"face"`
}

func (x *KYCAdminAddressDetail) GetCountry() string {
	if x != nil {
		return x.Country
	}
	return ""
}

func (x *KYCAdminAddressDetail) GetState() string {
	if x != nil {
		return x.State
	}
	return ""
}

func (x *KYCAdminAddressDetail) GetCity() string {
	if x != nil {
		return x.City
	}
	return ""
}

func (x *KYCAdminAddressDetail) GetFullAddress() string {
	if x != nil {
		return x.FullAddress
	}
	return ""
}

func (x *KYCAdminAddressDetail) GetPostalCode() string {
	if x != nil {
		return x.PostalCode
	}
	return ""
}

type ImgType int8

const (
	ImgTypeDocFront ImgType = iota
	ImgTypeDocBack
	ImgTypeFace
	ImgTypeLiveness
)

func (i ImgType) IsDocFront() bool {
	return i == ImgTypeDocFront
}

func (i ImgType) IsDocBack() bool {
	return i == ImgTypeDocBack
}

func (i ImgType) IsFace() bool {
	return i == ImgTypeFace
}

type KYCActionImage struct {
	IdempotentID string            `json:"idempotent_id"`
	MemberID     int64             `json:"member_id"`
	Provider     enums.KYCProvider `json:"provider"`
	AccountID    string            `json:"account_id"`
	RecordID     string            `json:"record_id"`
	ImgID        string            `json:"img_id"`
	ImgType      ImgType           `json:"img_type"`
}
